/*
 *Copyright 2021-2023 NERCIS
 *
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License.
 *You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *Unless required by applicable law or agreed to in writing, software
 *distributed under the License is distributed on an "AS IS" BASIS,
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *See the License for the specific language governing permissions and
 *limitations under the License.
 */

package cn.ac.nercis.pes.service.document.report;

import cn.ac.nercis.pes.common.utils.DataUtils;
import cn.ac.nercis.pes.model.bo.doc.report.evaluation.AppendixTwoBO;
import cn.ac.nercis.pes.model.bo.doc.report.evaluation.proof.*;
import cn.ac.nercis.pes.model.bo.doc.report.table.PersonQualificationReportBO;
import cn.ac.nercis.pes.model.dto.evaluation.content.proof.QualityDTO;
import cn.ac.nercis.pes.repository.model.project.SystemDO;
import cn.ac.nercis.pes.service.evaluation.ProofService;
import cn.ac.nercis.pes.service.utils.FileManage;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 密评活动有效性证明记录数据服务类
 * @author zpy
 * @version 1.0.0
 */
@Slf4j
@Service
public record ReportProofDataService(ProofService proofService) {

    private static final DateTimeFormatter LOCAL_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy年MM月dd日");


    @Autowired
    public ReportProofDataService(ProofService proofService){
        this.proofService = proofService;
    }

    public AppendixTwoBO getAppendixB(@NonNull SystemDO systemDO){
        var data = proofService.findQuality(systemDO.getId());
        return AppendixTwoBO.builder()
                .delegate(getDelegate(systemDO))
                .activity(getActivity(systemDO))
                .entryRecord(getEntryRecord(systemDO))
                .quality(getQuality(systemDO.getId(),data))
                .schemeReview(getSchemeReview(systemDO.getId(),data))
                .reportReview(getReportReview(systemDO.getId(),data))
                .person(getPerson(systemDO))
                .grading(getGrading(systemDO))
                .build();
    }

    private DelegateBO getDelegate(@NonNull SystemDO systemDO){
        var data = proofService.findDelegate(systemDO.getId());
        return DelegateBO.builder()
                .pictureDir(FileManage.getDelegateDir(systemDO.getId()))
                .fileType(data.getFileType())
                .date(toString(data.getDate()))
                .unit(data.getUnit())
                .amount(data.getAmount())
                .price(data.getPrice())
                .serviceFile(data.getServiceFile())
                .tollFile(data.getTollFile())
                .signFile(data.getSignFile())
                .build();
    }

    private ActivityBO getActivity(@NonNull SystemDO systemDO){
        var data = proofService.findActivity(systemDO.getId());
        return ActivityBO.builder()
                .pictureDir(FileManage.getActivityDir(systemDO.getId()))
                .startDate(toString(data.getStartDateTicket()))
                .endDate(toString(data.getEndDateTicket()))
                .unit(data.getUnitTicket())
                .person(data.getPersonTicket())
                .travelFile(data.getTravelFileTicket())
                .stayFile(data.getStayFileTicket())
                .stayInvoiceFile(data.getStayInvoiceFileTicket())
                .build();
    }

    private EntryRecordBO getEntryRecord(@NonNull SystemDO systemDO){
        var data = proofService.findActivity(systemDO.getId());
        return EntryRecordBO.builder()
                .pictureDir(FileManage.getActivityDir(systemDO.getId()))
                .startDate(toString(data.getStartDateRecord()))
                .endDate(toString(data.getEndDateRecord()))
                .unit(data.getUnitRecord())
                .address(data.getAddressRecord())
                .person(data.getPersonTicket())
                .signFormFile(data.getSignFormFileRecord())
                .scenePhotoFile(data.getScenePhotoFileRecord())
                .dockingFile(data.getDockingFileRecord())
                .inOutFile(data.getInOutFileRecord())
                .build();
    }

    private QualityBO getQuality(String systemId, @NonNull QualityDTO data){
        return QualityBO.builder()
                .pictureDir(FileManage.getQualityDir(systemId))
                .authFile(data.getAuthFileQuality())
                .noticeFile(data.getNoticeFileQuality())
                .build();

    }

    private SchemeReviewBO getSchemeReview(String systemId, @NonNull QualityDTO data){
        return SchemeReviewBO.builder()
                .pictureDir(FileManage.getQualityDir(systemId))
                .name(data.getNameScheme())
                .date(toString(data.getDateScheme()))
                .reviewRecordFile(data.getReviewRecordFileScheme())
                .confirmRecordFile(data.getConfirmRecordFileScheme())
                .build();
    }

    private ReportReviewBO getReportReview(String systemId, @NonNull QualityDTO data){
        return ReportReviewBO.builder()
                .pictureDir(FileManage.getQualityDir(systemId))
                .date(toString(data.getDateReport()))
                .scanFile(data.getScanFileReport())
                .build();
    }

    private PersonBO getPerson(@NonNull SystemDO systemDO){
        var prove = findEvaluatorQualificationsTable(systemDO.getId());
        var data = proofService.findEvaluatorProve(systemDO.getId());
        return PersonBO.builder()
                .pictureDir(FileManage.getProveDir(systemDO.getId()))
                .table(prove)
                .proveFile1(data.getProveFile1())
                .proveFile2(data.getProveFile2())
                .editorProveFile(data.getEditorProveFile())
                .auditProveFile(data.getAuditProveFile())
                .approveProveFile(data.getApproveProveFile())
                .build();
    }

    private List<PersonQualificationReportBO> findEvaluatorQualificationsTable(@NonNull String systemId) {
        try {
            var evaluatorDTOList = this.proofService.findEvaluatorQualifications(systemId);
            if (CollectionUtils.isEmpty(evaluatorDTOList)) {
                return evaluatorQualificationsTableByEmpty();
            }
            AtomicInteger number = new AtomicInteger(1);
            return  evaluatorDTOList.stream()
                    .map(e -> PersonQualificationReportBO.builder()
                            .name(DataUtils.toString(number.getAndIncrement()))
                            .name(e.getName())
                            .role(e.getRole())
                            .passDate(e.getPassDate())
                            .build())
                    .collect(Collectors.toList());
        } catch (RuntimeException rEx) {
            log.error("{}/getEvaluatorQualificationsTable 获取数据出错：{}", this.getClass().getName(), rEx.getMessage());
            throw rEx;
        }
    }

    private List<PersonQualificationReportBO> evaluatorQualificationsTableByEmpty(){
        return List.of(PersonQualificationReportBO.builder()
                .number("1")
                .name("")
                .role("")
                .passDate("")
                .build());
    }

    private GradingBO getGrading(@NonNull SystemDO systemDO){
        var data = this.proofService.findGrading(systemDO.getId());
        return GradingBO.builder()
                .pictureDir(FileManage.getGradingDir(systemDO.getId()))
                .name(data.getName())
                .date(toString(data.getDate()))
                .scanFile(data.getScanFile())
                .build();
    }

    private String toString(LocalDate date){
        return Objects.nonNull(date) ? LOCAL_DATE_FORMATTER.format(date) : StringUtils.EMPTY;
    }
}
